/*! ******************************************************************************
 *
 * Created on 2021年9月29日
 *
 * Copyright(c) YuZhou Big Data Laboratory CO.,Ltd, 2021. All rights reserved.
 */
package org.yzbdl.lanius.scannotation;

import org.apache.commons.io.IOUtils;
import org.scannotation.AnnotationDB;
import org.scannotation.archiveiterator.Filter;
import org.scannotation.archiveiterator.IteratorFactory;
import org.scannotation.archiveiterator.StreamIterator;
import org.yzbdl.lanius.authorize.decrypt.jar.ClassDecrypt;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * AnnotationDB扩展,在类注释扫描前解密类文件
 *
 * @author hs@yzbdl.ac.cn
 */
public class LaniusAnnotationDB extends AnnotationDB {
    private static final long serialVersionUID = 1L;

    @Override
    public void scanArchives(URL... urls) throws IOException {
        for (URL url : urls) {
            Filter filter = new Filter() {
                @Override
                public boolean accepts(String filename) {
                    if (filename.endsWith(".class")) {
                        // 不清楚其作用，暂时注释掉
                        // if (filename.startsWith("/")){
                        // filename = filename.substring(1);
                        // }
                        if (!ignoreScan(filename.replace('/', '.'))) {
                            return true;
                        }
                    }
                    return false;
                }
            };

            StreamIterator it = IteratorFactory.create(url, filter);

            InputStream stream;
            while ((stream = it.next()) != null) {
                scanClass(stream);
            }
        }
    }

    @Override
    public void scanClass(InputStream bits) throws IOException {
        byte[] buf = ClassDecrypt.decryptClassToBytes(IOUtils.toByteArray(bits));
        InputStream is = new ByteArrayInputStream(buf);
        super.scanClass(is);
    }

    private boolean ignoreScan(String intf) {
        for (String ignored : ignoredPackages) {
            if (intf.startsWith(ignored + ".")) {
                return true;
            }
        }
        return false;
    }

}
